#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "maquina_tx_pc.h"
#include <cv.h>
#include <highgui.h>
#include <QDateTime>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    BaudMap.insert(  "9600", B9600	);
    BaudMap.insert(  "19200",B19200	);
    //    BaudMap.insert(  "38400", B38400	);
    //    BaudMap.insert(  "57600", B57600   );
    BaudMap.insert(  "115200", B115200  );
    //    BaudMap.insert(  "230400", B230400  );
    //    BaudMap.insert(  "460800", B460800  );
    //    BaudMap.insert(  "500000", B500000  );
    //    BaudMap.insert(  "576000", B576000  );
    //    BaudMap.insert(  "921600", B921600  );
    //    BaudMap.insert(  "1000000", B1000000 );
    //    BaudMap.insert(  "1152000", B1152000 );
    //    BaudMap.insert(  "1500000", B1500000 );
    //    BaudMap.insert(  "2000000", B2000000 );
    //    BaudMap.insert(  "2500000", B2500000 );
    //    BaudMap.insert(  "3000000", B3000000 );
    //    BaudMap.insert(  "3500000", B3500000 );
    //    BaudMap.insert(  "4000000", B4000000 );

    QList<int> llaves = BaudMap.values();
    for (int i = 0; i < llaves.size(); i++) {
        ui->BaudRateList->insertItem(i, BaudMap.key(llaves[i]));
    }

    bFinish = false;

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_InitializeSerialPort_clicked()
{
    uint32_t baudrate = BaudMap.value(ui->BaudRateList->currentText());
    char *a = ui->SerialPortList->currentText().toLocal8Bit().data();
    SerialPort = inicializarPuerto(a,baudrate);

    if (SerialPort == -1)
        errmsg.showMessage("Could not open serial port!");
    else
    {
        ui->BaudRateList->setEnabled(false);
        ui->InitializeSerialPort->setEnabled(false);
        ui->SerialPortList->setEnabled(false);
    }

    //Como saber si la velocidad deseada esta disponible?

}


void MainWindow::on_SendButton_clicked()
{
    char Readings[255];

    ui->SendingStatus->setText("Sending "+ui->CommandList->currentText());

    switch (ui->CommandList->currentIndex())
    {
    case 0:
        if (enviarStop())
        {
            ui->SendingStatus->setText("ACK STOP");
        }
        break;
    case 1:
        historicMax = ui->horizontalSlider->value();

        while(!bFinish) {
            uint32_t numBytes;

            numBytes = 0;
            vaciaBufferLectura();

            if ((numBytes = leerComandoLargo(Readings)) == NUM_BYTES) {
                escribirValoresVentana(Readings);
            }else {
                qDebug()<< numBytes;
            }

            QCoreApplication::processEvents();

        }
        break;

    case 2:
        QDateTime dateTime = QDateTime::currentDateTime();
        QString dateTimeString = dateTime.toString("yyyyMMdd_hhmmss");
        QDir directorio(QDir::current());
        QFile file;
        CvCapture* capture = cvCaptureFromCAM(1);
        char Readings[255];
        int bucleIndex = 0;

        if ( !capture ) {
            fprintf( stderr, "ERROR: capture is NULL \n" );
            break;
        }

        directorio.mkdir(dateTimeString);
        directorio.cd(dateTimeString);
        QDir::setCurrent(directorio.absolutePath());
        file.setFileName("readings.bin");
        file.open(QIODevice::WriteOnly);
        QDataStream out(&file);
        out.setVersion(QDataStream::Qt_4_8);

        cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 320);
        cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 240);

        // Create a window in which the captured images will be presented
        cvNamedWindow( "mywindow", CV_WINDOW_AUTOSIZE );
        historicMax = ui->horizontalSlider->value();

        // Show the image captured from the camera in the window and repeat
        while (!bFinish) {
            IplImage* frame = cvQueryFrame( capture );
            if ( !frame ) {
                fprintf( stderr, "ERROR: frame is null...\n" );
                getchar();
                break;
            }
            cvShowImage( "mywindow", frame );
            // Do not release the frame!

            //Guardar los datos de las barras en el archivo
            vaciaBufferLectura();
            if (leerComandoLargo(Readings) == NUM_BYTES) {
                QVector<uint8_t> barras(NUM_BYTES);
                //float posLinea = *((float *)(&Readings[INDEX_POS_LINEA]));

                for (int i = 0; i < NUM_BYTES; i++) {
                    barras[i] = (uint8_t)Readings[i];
                }

                //escribirValoresVentana(Readings, posLinea);
                out << barras;
            }

            //Save the image into a jpeg file
            cvSaveImage((QString().sprintf("%05d", bucleIndex) + ".jpg").toLocal8Bit(), frame);

            bucleIndex++;
            //If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version),
            //remove higher bits using AND operator

            if ( (cvWaitKey(1) & 255) == 27 ) break;
            QCoreApplication::processEvents();
        }

        file.close();

        // Release the capture device housekeeping
        cvReleaseCapture( &capture );
        cvDestroyWindow( "mywindow" );

        break;
    }
}

void MainWindow::escribirValoresVentana(char *Readings)
{
    uint16_t *Luminosidad_Barra_Frontal;
    uint16_t *Calibraciones_Frontal_Oscuro;
    uint16_t *Calibraciones_Frontal_Claro;
    uint16_t *Luminosidad_Barra_Trasera;
    uint16_t *Calibraciones_Trasera_Oscuro;
    uint16_t *Calibraciones_Trasera_Claro;
    float Posicion_Linea;
    float Velocidad_m_s;
    uint16_t Salida_Direccion;
    uint32_t valoresBarras[40];
    float *fHistograma;

    Luminosidad_Barra_Frontal = (uint16_t *)(&Readings[INDEX_Luminosidad_Barra_Frontal]);
    Calibraciones_Frontal_Oscuro = (uint16_t *)(&Readings[INDEX_Calibraciones_Frontal_Oscuro]);
    Calibraciones_Frontal_Claro = (uint16_t *)(&Readings[INDEX_Calibraciones_Frontal_Claro]);
    Luminosidad_Barra_Trasera = (uint16_t *)(&Readings[INDEX_Luminosidad_Trasera]);
    Calibraciones_Trasera_Oscuro = (uint16_t *)(&Readings[INDEX_Calibraciones_Trasera_Oscuro]);
    Calibraciones_Trasera_Claro = (uint16_t *)(&Readings[INDEX_Calibraciones_Trasera_Claro]);
    Posicion_Linea = *((float *)(&Readings[INDEX_Posicion_Linea]));
    Velocidad_m_s = *((float *)(&Readings[INDEX_Velocidad_m_s]));
    Salida_Direccion = *((uint16_t *)(&Readings[INDEX_Salida_Direccion]));

    //Escribir los valores obtenidos en los indicadores de barras frontales
    QList<QObject*> barrasFront = ui->FrameBarrasFront->children();
    for (int i = 1; i < barrasFront.size(); i++) {
        valoresBarras[i-1] = Luminosidad_Barra_Frontal[i-1];
        ((QProgressBar*)barrasFront[i])->setMaximum(historicMax);
        ((QProgressBar*)barrasFront[i])->setValue((Luminosidad_Barra_Frontal[i-1] > historicMax) ? historicMax : Luminosidad_Barra_Frontal[i-1]);
    }

    //Escribir los valores obtenidos en los indicadores de barras traseras
    QList<QObject*> barrasTras = ui->FrameBarrasTras->children();
    for (int i = 1; i < barrasTras.size(); i++) {
        valoresBarras[i+24-1] = Luminosidad_Barra_Trasera[i-1];
        ((QProgressBar*)barrasTras[i])->setValue((Luminosidad_Barra_Trasera[i-1] > historicMax) ? historicMax : Luminosidad_Barra_Trasera[i-1]);
        ((QProgressBar*)barrasTras[i])->setMaximum(historicMax);
    }

    miHistograma.setCalibraciones(Calibraciones_Frontal_Oscuro, Calibraciones_Frontal_Claro, Calibraciones_Trasera_Oscuro, Calibraciones_Trasera_Claro);
    miHistograma.getPosicionLinea2(valoresBarras, 0, 1, 5);
    fHistograma = miHistograma.getHistograma();

    //Escribir los valores obtenidos en los indicadores de histograma
    QList<QObject*> barrasHist = ui->histogramaLayout->children();
    for (int i = 0; i < barrasHist.size() - 1; i++) {
        ((QProgressBar*)barrasHist[i])->setValue((int)(fHistograma[i]*100));
    }

    ui->posicionLinea->setValue((int)(Posicion_Linea*100));
}

void MainWindow::on_horizontalSlider_valueChanged(int value)
{
    historicMax = value;
}

void MainWindow::closeEvent(QCloseEvent *)
{
    bFinish = true;
}

void MainWindow::on_pushButton_clicked()
{
    bFinish = true;
}
